package testwebsocketserver;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class HttpRequest
{
    public enum HttpRequestType { GET, POST };
    private HttpRequestType requestType;
    private String requestedURI;
    public enum HttpVersion { v1_0, v1_1 };
    private HttpVersion httpVersion;
    
    private Map<String, String> headers = new HashMap<String, String>();
    
    public HttpRequest(String firstRequestLine)
    {
        if ( ! firstRequestLine.matches("^(GET|POST) /\\S* HTTP/1\\.[01]$"))
        {
            throw new IllegalArgumentException("Passed line \"" + firstRequestLine +
                    "\" doesn't look like HTTP request first line");
        }
        
        String[] parts = firstRequestLine.split(" ");
        if (parts[0].equalsIgnoreCase("GET"))
        {
            requestType = HttpRequestType.GET;
        }
        else if (parts[0].equalsIgnoreCase("POST"))
        {
            requestType = HttpRequestType.POST;
        }
        else
        {
            throw new UnsupportedOperationException("HTTP method " + parts[0] + " is not supported");
        }
        
        requestedURI = parts[1];
        
        if (parts[2].equalsIgnoreCase("HTTP/1.0"))
        {
            httpVersion = HttpVersion.v1_0;
        }
        else if (parts[2].equalsIgnoreCase("HTTP/1.1"))
        {
            httpVersion = HttpVersion.v1_1;
        }
        else
        {
            throw new UnsupportedOperationException("HTTP version " + parts[2] + " is not supported");
        }
    }
    
    public void readHeaders(BufferedReader in) throws IOException
    {
        String readLine;
        while ((readLine = in.readLine()) != null)
        {
            if (readLine.equalsIgnoreCase(""))
            {
                // End of headers
                return;
            }
            
            if ( ! readLine.matches("^[a-zA-Z\\-]+: \\S+$"))
            {
                throw new IllegalArgumentException("Received header \"" + readLine + "\" has bad syntax");
            }
            String[] parts = readLine.split(": ");
            setHeader(parts[0], parts[1]);
        }
        
        // readLine == null, connection interrupted?
        throw new IOException("Connection closed before all headers were sent");
    }
    
    public void setHeader(String key, String value)
    {
        headers.put(key, value);
    }
    
    public String getHeader(String key)
    {
        return headers.get(key);
    }
    
    public HttpRequestType getRequestType()
    {
        return requestType;
    }
    
    public String getRequestedURI()
    {
        return requestedURI;
    }
    
    public HttpVersion getHttpVersion()
    {
        return httpVersion;
    }
    
    public boolean isWebsocketHandshakeRequest()
    {
        // TODO Do more specific check
        return "websocket".equalsIgnoreCase(getHeader("Upgrade"));
    }
    
    @Override
    public String toString()
    {
        StringBuilder output = new StringBuilder();
        output.append("Method: ");
        output.append(((requestType == HttpRequestType.GET) ? "GET" : "POST"));
        output.append("\nResource: ");
        output.append(requestedURI);
        output.append("\nHTTP version: ");
        output.append((httpVersion == HttpVersion.v1_0 ? "1.0" : "1.1"));
        output.append("\n");
        output.append(headers.entrySet().toString());
        return output.toString();
    }
}
